#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：api_testing 
@File    ：assert_control.py
@IDE     ：PyCharm 
@Author  ：future76
@Date    ：2024/6/26 9:21 
@Desc    ：断言类型封装，支持json响应断言、正则表达式响应断言、数据库断言
"""
# 标准库导入
import json
import types
# 第三方库导入
import allure
from requests import Response
from loguru import logger
# 本地应用/模块导入
from utils.assertion_utils import assert_function
from utils.data_utils.extract_data_handle import json_extractor


class AssertUtils:

    def __init__(self, assert_data, response: Response = None):
        """
        断言处理
        :param assert_data: 断言数据,如{'eq': {'http_code': 200, '$.login': '${login}'}}
        :param response: 接口响应数据
        """
        self.assert_data = assert_data
        self.response = response
        self.assert_d = self.assert_data.get("actualJsonpath")

    def assert_handle(self, data):
        """
        断言操作
        """
        # 如果存在断言的数据，并且数据的类型是字典
        if data and isinstance(data, dict):
            for k, v in data.items():
                if k.lower() == "status_code":
                    with allure.step("断言 --> 响应状态码"):
                        assert_function.eq(expect_value=v, actual_value=self.response.status_code)
                else:
                    for act, exp in v.items():
                        actual_value = json_extractor(obj=self.response.json(), expr=f'$..{act}')
                        expect_value = exp
                        logger.debug(
                            f"assert_type: {k}\n"
                            f"expect_value: {expect_value}\n"
                            f"actual_value: {actual_value}\n")
                        message = f"断言 --> 预期结果：{type(expect_value)} || {expect_value} 实际结果：{type(actual_value)} || {actual_value} ||\n 字段名：{act}"
                        with allure.step(message):
                            getattr(assert_function, k)(expect_value=expect_value, actual_value=actual_value,message=message)
        else:
            logger.debug(f"断言数据为空或者不是字典格式，跳过断言！\n"
                         f"断言数据：{self.assert_data}")

    def one_assert_handle(self):
        """
        单个断言方式
        """
        logger.info("\n开始断言----------------------------------------------------")
        # 实际结果
        actual_value = json_extractor(obj=self.response.json(), expr=f'$..{self.assert_data["actualJsonpath"]}')
        # 预期结果
        expect_value = self.assert_data["expectData"]

        # 将断言方式改成反射
        logger.debug(
            f'\n断言类型: {self.assert_data["assertType"]}\n'
            f"断言预期值: {expect_value}\n"
            f"断言实际值: {actual_value}")
        message = f"断言 --> 预期结果：{type(expect_value)} || {expect_value} 实际结果：{type(actual_value)} || {actual_value}||\n 字段名：{self.assert_data['actualJsonpath']}"
        with allure.step(message):
            getattr(assert_function, self.assert_data["assertType"])(expect_value=expect_value, actual_value=actual_value, message=message)
        logger.info("\n断言结束----------------------------------------------------")

    def select_assert_handle(self):
        """自动切换多个断言和单个断言"""
        try:
            # 如果是断言类似于[]的,建议使用多断言，可以保持其类型
            data = json.loads(self.assert_d)
            self.assert_handle(data)
        except json.JSONDecodeError:
            self.one_assert_handle()


if __name__ == '__main__':
    a = {'id': 3, 'featureName': 'F01_视频号列表', 'caseName': '在线状态为在线',
         'path': 'jingtun-no-manage/videoAccInfo/pageListVideoWxAccInfo', 'method': 'post',
         'headers':
             '{"Content-Type":"application/json",\n"Authorization":  "Bearer 191b3d93-99c3-47f2-9e02-204c36a4a796","Isyou":"6CF0177C70D93D01D52A31AEC1A71619+-=,1F26A3D1F4D6C1EF1D06046E80D1F6CE+-="}',
         'params': None,
         'data':
             '{"groupId":0,"businessType":"","limit":10,"page":1,"isClose":"","isOnline":"1","isCanceled":"","isOpenVideo":"","uniqueType":"3","uniqueParam":[],"startRecycleTime":"","endRecycleTime":"","startCloseTime":"","endCloseTime":"","openStartTime":"","openEndTime":"","startExpireTime":"","endExpireTime":"","sourceType":"","isHaveShopCar":"","isCompliance":"","isHaveHeating":"","isGoodHaveHeating":"","isAllot":"","startPostVideoCount":"","endPostVideoCount":"","startFansCount":"","endFansCount":"","isRecycle":"","enabled":"","merchantType":"","merchantId":"","hyMerchantId":"","wxProtocolType":"","personalityEditInfo":[],"majorViolation":{"end":"","start":""},"minorViolation":{"end":"","start":""},"visionBottoms":[],"smallVersions":[],"bigVersion":[],"region":"","osVersion":"","reportStatus":"","platMerchantNoList":[],"nickNameLike":"","industryId":"","isThousandFans":"","isRealName":"","isRaising":"","isTruthVerify":"","openTimeAfter":"","isExpired":"","isLimit":""}',
         'type': 'json', 'assertType': 'one_to_many', 'actualJsonpath': 'wxIsOnline', 'expectData': 1,
         'result': '测试通过，断言成功。', 'jsonExData': None, 'is_true': True
         }
    b= {'eq': {'http_code': 200, '$.login': '${login}'}}
    c = {'eq': {'http_code': 200, '$.user_id': 84954}, 'in': {'$.login': 'auotest'},
         'gt': {'$.user_id': 84955}, 'lt': {'$.user_id': 84953}, 'not': {'$.user_id': 85390}}
    # for k, v in a.items():
    #     print(k)
    #     print(v)
    #     for i,j in v.items():
    #         print(i)
    #         print(j)
    aa = '{"status_code": 200,"one_to_many": {"limitInfos": []}}'
    data = json.loads(aa)
    print(data,type(data))
    print(type(data["one_to_many"]["limitInfos"]))